/*******************************************************************************
 * Copyright (c) 2010 marvin.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 * Contributors:
 *     marvin - initial API and implementation
 ******************************************************************************/

package com.marv42.ebt.newnote.scanning;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpProtocolParams;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;

import com.marv42.ebt.newnote.EbtNewNote;
import com.marv42.ebt.newnote.R;



public class DenominationGuesser extends AsyncTask<String, Void, String>
{
   private static final String COLOR_ANALYSIS_HOST = "http://mkweb.bcgsc.ca/color_summarizer";

   private static final int DENOMINATION_NOTIFICATION_ID = 3;

   private EbtNewNote mEbtObject;



   public DenominationGuesser(final EbtNewNote ebtObject)
   {
      mEbtObject = ebtObject;
   }



   @Override
   protected String
   doInBackground(String... params)
   {
      return guess(params[0]);
   }



   @Override
   protected void
   onPostExecute(String denominationResult)
   {
      if (denominationResult == "")
         return;

      mEbtObject.setDenominationResult(denominationResult);

      String r = mEbtObject.getString(R.string.denomination_return);

      Notification notification = new Notification(
         R.drawable.ic_stat_notify_ebt_white, r, System.currentTimeMillis());
      notification.flags = Notification.FLAG_AUTO_CANCEL;

      String contentTitle = mEbtObject.getString(R.string.denomination_return);
      String contentText  = mEbtObject.getString(R.string.denomination_return_detailed);

      notification.setLatestEventInfo(
         mEbtObject, contentTitle, contentText, PendingIntent.getActivity(
            mEbtObject, 0, new Intent(mEbtObject, EbtNewNote.class),
            PendingIntent.FLAG_UPDATE_CURRENT|Intent.FLAG_ACTIVITY_NEW_TASK));

      ((NotificationManager) mEbtObject.getSystemService(
            Context.NOTIFICATION_SERVICE)).notify(DENOMINATION_NOTIFICATION_ID, notification);
   }



   private String
   guess(String url)
   {
      // url = "http://upload.wikimedia.org/wikipedia/commons/thumb/5/56/EUR_5_reverse_%282002_issue%29.jpg/220px-EUR_5_reverse_%282002_issue%29.jpg";
      String content = "";
      try
      {
         String uri = COLOR_ANALYSIS_HOST + "/?text=1&url=" +
                      url + "&precision=extreme";
         HttpGet request = new HttpGet(uri);

         HttpClient httpClient = new DefaultHttpClient();
         HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);

         InputStream is = httpClient.execute(request).getEntity().getContent();
         BufferedReader br = new BufferedReader(new InputStreamReader(is));
         boolean dataStarted = false;
         String line = "";
         while ((line = br.readLine()) != null)
         {
            if (line.startsWith("variable"))
            {
               content += line;
               Log.d(EbtNewNote.LOG_TARGET, "color analysis: " + line);
               dataStarted = true;
            }
            if (dataStarted && ! line.startsWith("variable"))
                break;
         }
      }
      catch (UnsupportedEncodingException e)
      {
         Log.e(EbtNewNote.LOG_TARGET, e.getClass().getSimpleName() + ": " + e.getMessage());
      }
      catch (ClientProtocolException e)
      {
         Log.e(EbtNewNote.LOG_TARGET, e.getClass().getSimpleName() + ": " + e.getMessage());
      }
      catch (IOException e)
      {
         Log.e(EbtNewNote.LOG_TARGET, e.getClass().getSimpleName() + ": " + e.getMessage());
      }
      catch (ParseException e)
      {
         Log.e(EbtNewNote.LOG_TARGET, e.getClass().getSimpleName() + ": " + e.getMessage());
      }

      Pattern pattern = Pattern.compile("value (\\d{1,3}) rgb", Pattern.UNICODE_CASE);
      Matcher matcher = pattern.matcher(content);
      if (matcher.find())
         return Hue2Denomination(matcher.group(1));

      Log.d(EbtNewNote.LOG_TARGET, "no denmomination result");
      return "";
   }



   private String
   Hue2Denomination(String integer)
   {
      Log.d(EbtNewNote.LOG_TARGET, "hue value: " + integer);

      int i;
      try{
         i = Integer.parseInt(integer);
      }
      catch (NumberFormatException e)
      {
         Log.e(EbtNewNote.LOG_TARGET, e.getMessage());
         return "";
      }

      // hue   8  32  40 117 129 188 314 360
      //  €   10  50 200 100  5   20 500  10

      String denomination = "";
      if (i >  251 && i <  337)
                                 denomination = "500";
      if (i >   36 && i <   79)
                                 denomination = "200";
      if (i >=  79 && i <  123)
                                 denomination = "100";
      if (i >   20 && i <   36)
                                 denomination =  "50";
      if (i >  159 && i <= 251)
                                 denomination =  "20";
      if (i <=  20 || i >= 337)
                                 denomination =  "10";
      if (i >= 123 && i <= 159)
                                 denomination =   "5";
      denomination += " €";
      denomination += " (" + integer + ")";
      Log.d(EbtNewNote.LOG_TARGET, "suggesting denomination: " + denomination);

      return denomination;
   }
}
